package gutils

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"math"
	"net/url"
	"reflect"
	"strconv"
)

func IntToStr(intData int) string {
	strData := strconv.Itoa(intData)
	return strData
}

func Int64ToStr(int64Data int64) string {
	strData := strconv.FormatInt(int64Data, 10)
	return strData
}

func Int64ToStrByBase(int64Data int64, base int) string {
	strData := strconv.FormatInt(int64Data, base)
	return strData
}

func StrToBytes(str string) []byte {
	var b []byte = []byte(str)
	return b
}

func BytesToStr(bytes []byte) string {
	return string(bytes)
}

func StrToMapInterface(str string) (map[string]interface{}, error) {
	m := make(map[string]interface{})
	err := json.Unmarshal([]byte(str), &m)
	return m, err
}

func MapInterfaceToStr(mapData map[string]interface{}) string {
	bytesData, err := json.Marshal(mapData)
	if err != nil {
		return ""
	}
	return string(bytesData)
}

func InterfaceToSlice(data interface{}) []interface{} {
	var res []interface{}
	value := reflect.ValueOf(data)
	if value.Kind() != reflect.Slice && value.Kind() != reflect.Array {
		return nil
	}
	for i := 0; i < value.Len(); i++ {
		res = append(res, value.Index(i).Interface())
	}
	return res
}

func StrToInt64(str string) (int64, error) {
	return strconv.ParseInt(str, 10, 64)
}

func StrToFloat64(str string) (float64, error) {
	return strconv.ParseFloat(str, 64)
}

// 保留n位小数
func RoundFloat64(f float64, n int) float64 {
	return float64(int(f*float64(math.Pow10(n)))) / float64(math.Pow10(n))
}

func StrToBase64(str string) string {
	msg := []byte(str)
	encoded := base64.StdEncoding.EncodeToString(msg)
	return encoded
}

func Base64ToStr(str string) string {
	decoded, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return ""
	} else {
		return string(decoded)
	}
}

func StuToMapInterface(modelStu interface{}) (map[string]interface{}, error) {
	data, err := json.Marshal(modelStu)
	if err != nil {
		return nil, err
	}
	m := make(map[string]interface{})
	err = json.Unmarshal(data, &m)
	return m, err
}

func MapInterfaceToStu(stu interface{}, data map[string]interface{}) error {
	arr, err := json.Marshal(data)
	if err != nil {
		return err
	}
	err = json.Unmarshal(arr, stu)
	if err != nil {
		return err
	}
	return nil
}

// 16位16进制数
func StrToMd516(str string) string {
	data := []byte(str)
	has := md5.Sum(data)
	value := fmt.Sprintf("%x", has)
	return value[8:24]
}

// 32位16进制数
func StrToMd532(str string) string {
	data := []byte(str)
	has := md5.Sum(data)
	return fmt.Sprintf("%x", has)
}

// 40位16进制数
func StrToSha1(str string) string {
	data := []byte(str)
	has := sha1.Sum(data)
	return fmt.Sprintf("%x", has)
}

// 64位16进制数
func StrToSha256(str string) string {
	data := []byte(str)
	has := sha256.Sum256(data)
	return fmt.Sprintf("%x", has)
}

// 128位16进制数
func StrToSha512(str string) string {
	data := []byte(str)
	has := sha512.Sum512(data)
	return fmt.Sprintf("%x", has)
}

func QueryEscape(urlStr string) string {
	return url.QueryEscape(urlStr)
}

func QueryUnescape(urlStr string) (string, error) {
	return url.QueryUnescape(urlStr)
}

func XmlToStu(xmlStr string, v interface{}) error {
	body := []byte(xmlStr)
	return xml.Unmarshal(body, v)
}

func StuToXml(stu interface{}) (string, error) {
	xmlData, err := xml.Marshal(stu)
	if err != nil {
		return "", err
	}
	return string(xmlData), nil
}
